#include "Tokenizer.h"
#include "Token.h"
#include "TokenNode.h"

#include <iostream>

using std::cout;
using std::endl;

Tokenizer::Tokenizer(string const & str)  
{
    tokenize(str);	    
} 

void Tokenizer::tokenize(string const & str)
	{			
		size_t size=str.size();
		size_t i=0;
		string operats="+*-/()^";	
				
		while (i!=size)
		{						
			size_t j=i;	
			if (operats.find(str[i]) != string::npos)	
			{				
				if ((i!=0)&&(str[i-1]==')')&&(str[i]=='('))
				    tokens.push_back (Token("*", Operation));				
				string s=str.substr(i, 1);
				if ((s=="(") || (s==")"))
					tokens.push_back (Token(s, Bracket));
				else
					tokens.push_back (Token(s, Operation));
			}
			else if(isdigit(str[i]))
			{					
				if ((i!=0)&&(str[i-1]==')'))
				    tokens.push_back (Token("*", Operation));				
				while ((i!=(size-1)) && (isdigit(str[i+1])))
					++i;
				string s;
				if (i!=j)
					s=str.substr(j, (i-j+1));
				else
					s=str.substr(i, 1);
				tokens.push_back (Token(s, Number));				
				if ((i!=(size-1))&&(isalpha(str[i+1]) || (str[i+1]=='(')))
					tokens.push_back (Token("*", Operation));				
			}
			else if(isalpha(str[i]))
			{					
				if ((i!=0)&&(str[i-1]==')'))
				    tokens.push_back (Token("*", Operation));				
				while ((i!=(size-1))&&((isalpha(str[i+1])) || (isdigit(str[i+1]))))
					++i;
				string s;
				if (i!=j)
					s=str.substr(j, (i-j+1));
				else
					s=str.substr(i, 1);	
				tokens.push_back (Token(s, Variable));
				if (i!=(size-1))
				{
					if ((i!=size-1)&&( (str[i+1]=='(') && (s.compare("sin") != 0) && (s.compare("cos") != 0)))
					tokens.push_back (Token("*", Operation));
				}
			}	
			++i;
		}		
	}

Tokenizer::const_iterator Tokenizer::begin() const { return tokens.begin();  }
Tokenizer::const_iterator Tokenizer::end()   const { return (tokens.end()-1);}

void printTokens(const_iterator begin, const_iterator end)
{			
	cout <<"Token's vector"<< endl;
	for (const_iterator it=begin; it<=end; ++it)
		cout << it->getText()<<" ";		
	cout <<endl;
}
